# __author__ = 'heyin'
# __date__ = '2018/12/25 10:22'
import os
import time
import json
import pandas as pd
import numpy as np
import requests

from stock.utils import timestamp2date


def download(stockcode):
    """从雅虎股票获取数据"""
    # 构造首次请求url，用以获取首次交易的时间
    first_url = 'https://query1.finance.yahoo.com/v8/finance/chart/{}?symbol={}&interval=1d'.format(stockcode,
                                                                                                    stockcode)
    # print(first_url)
    first_resp = requests.get(first_url).content.decode('utf-8')

    if json.loads(first_resp).get('chart').get('result') is None:
        error = json.loads(first_resp).get('chart').get('error').get('description')
        return error
    first_trade_date = json.loads(first_resp).get('chart').get('result')[0].get('meta').get('firstTradeDate')
    # 构造请求所有数据的url
    all_url = 'https://query1.finance.yahoo.com/v8/finance/chart/{}?symbol={}&period1={}&period2={}&interval=1d'.format(
        stockcode, stockcode, first_trade_date, int(time.time()))
    # print(all_url)
    print('发起%s的数据请求' % stockcode)
    all_resp = requests.get(all_url).content.decode('utf-8')

    result = json.loads(all_resp).get('chart').get('result')[0]

    # meta = result.get('meta')
    timestamp = result.get('timestamp')  # 从北京时间 1971-2-5 22:30 开始  到现今每天的同一时刻。注意此为开盘时间
    quote = result.get('indicators').get('quote')[0]

    # 时间戳转为具体日期
    date_ = list()
    for t in timestamp:
        # print(t)
        date_.append(timestamp2date(t))

    high = quote.get('high')
    low = quote.get('low')
    open_ = quote.get('open')
    close = quote.get('close')
    volume = quote.get('volume')  # 2462430000  24亿  写入原始数据，需要的时候自行处理

    day_data = np.array([open_, close, low, high], dtype=np.float64)
    # 将None替换为nan
    day_data[day_data == None] = np.nan

    day_data = day_data.T
    day_data = np.around(day_data, 3)

    date_ = np.array(date_).reshape((day_data.shape[0], 1))
    volume = np.array(volume).reshape((day_data.shape[0], 1))
    day_data = np.hstack((np.array(date_), day_data, np.array(volume)))
    stock_data = pd.DataFrame(day_data, columns=['date', 'open', 'close', 'low', 'high', 'volume'])
    stock_data.to_csv('./stockdata/%s.csv' % stockcode, header=True, index=False)
    # return stock_data  # 返回df


def read_local_csv(stockcode):
    """从本地文件读取数据返回df"""
    stock_data = pd.read_csv('./stockdata/%s.csv' % stockcode, parse_dates=[1])
    return stock_data


def download_or_read(stockcode):
    """判断本地是否有此股票的文件数据"""
    if os.path.exists('./stockdata/%s.csv' % stockcode):
        return True
    else:
        return False


def mov_avg(stockdata, ma):
    stockdata['ma_' + str(ma)] = stockdata['close'].rolling(ma).mean().round(2)
    return stockdata


def strategy(stock_data, start_date, ma):
    """上穿某个均线买入，跌穿某个均线卖出"""
    ma = 'ma_%s' % ma
    stock_data = stock_data.set_index('date', drop=True).loc[start_date:, ['open', 'close', ma]]
    # print(stock_data)
    isbuy = False  # 是否买入
    yes_dopen, yes_close, yes_date, yes_ma = None, None, None, None  # 变量保存昨日信息，用以均线比较计算
    buy_price = None  # 买入价
    shouyi_list = list()
    for index, data in stock_data.iterrows():
        _ma = data[ma]
        dopen = data['open']
        close = data['close']
        # print(type(yes_ma), type(_ma), type(yes_close))
        if all([yes_dopen, yes_close, yes_date, yes_ma]):
            if yes_close < yes_ma and close > _ma and isbuy is False:
                # print(index, dopen, close, _ma, '上穿%s均线，买入, 买入价%s' % (ma, close))
                buy_price = close
                isbuy = True
            elif yes_close > yes_ma and close < _ma and isbuy is True:
                diff_price = round((close - buy_price) / buy_price, 2)
                shouyi_list.append(diff_price)
                # print(index, dopen, close, _ma, '下穿%s均线，卖出, 卖出价%s，收益%s%%' % (ma, close, diff_price * 100))
                isbuy = False

        yes_dopen, yes_close, yes_date, yes_ma = dopen, close, index, _ma
    return shouyi_list  # 返回每次交易的涨跌幅度的列表


def shouyi(shouyi: list, money):
    """通过计算得到对应本金的收益情况"""
    j = money
    for i in shouyi:
        money = money * (1 + i)
    return round(money - j, 2), round(money, 2), '收益率%s%%' % round((money - j) / j * 100)


def run(stockcode, ma, startdate, money):
    """运行主逻辑处理"""
    # stockcode = 'AAPL'

    if not download_or_read(stockcode):  # 本地文件不存在
        stockdata = download(stockcode)  # 下载数据
        if isinstance(stockdata, str):
            print(stockdata)  # 股票代号错误，输出信息
            return
    # 均从本地读取文件数据，否则网络下载数据会报str和float无法进行计算
    stockdata = read_local_csv(stockcode)
    # 计算指定均线，返回值中数据已带有均线数据
    stockdata = mov_avg(stockdata, ma)
    # print(stockdata)
    # 计算每次交易的盈亏百分比
    shouyi_list = strategy(stockdata, startdate, ma)
    # 计算总收益
    income = shouyi(shouyi_list, money)  # (不含本金，含本金)
    # print(shouyi_list)
    now_year = int(timestamp2date(time.time()).split('-')[0])
    start_year = int(startdate.split('-')[0])
    print('根据均线 %s 计算的 %s %s 年收益率为' % (ma, stockcode, now_year - start_year), income)
    print('*' * 50)


if __name__ == '__main__':
    ma_list = [100]
    start_date = ['1988-12-01', '1998-12-01', '2008-12-01', '2013-12-01']
    for date in start_date:
        for ma in ma_list:
            run('^GSPC', ma, date, 10000)
